const path = require('path');
const axios = require('axios');
const webpack = require('webpack');
const MemoryFS = require('memory-fs');
const vm = require('vm');
const NativeModule = require('module');
const proxy = require('http-proxy-middleware');
const serverRender = require('./server-render');

const mfs = new MemoryFS();
const webpackServerConfig = require('../../webpack.config.server');

const serverCompiler = webpack(webpackServerConfig);
serverCompiler.outputFileSystem = mfs;

//难得一逼
const getModuleFromString = (bundle, filename) => {
  const m = { exports: {} }
  const wrapper = NativeModule.wrap(bundle)
  const script = new vm.Script(wrapper, {
    filename: filename,
    displayErrors: true
  })
  const result = script.runInThisContext()
  result.call(m.exports, m.exports, require, m)
  return m;
}

let serverBundle;

// 监听webpack文件变化
serverCompiler.watch({}, (err, stats) => {
  if(err) throw err;
  stats = stats.toJson();
  stats.errors.forEach(err => console.error(err));
  stats.warnings.forEach(warn => console.warn(warn));
  const bundlePath = path.join(
    webpackServerConfig.output.path,
    webpackServerConfig.output.filename
  );
  const bundle = mfs.readFileSync(bundlePath, 'utf-8');
  const m = getModuleFromString(bundle, 'server-entry.js');
  serverBundle = m.exports;
})

// get本地静态文件index.html
const getTemplate = () => {
  return new Promise((resolve, reject) => {
    axios.get('http://localhost:7000/public/server.ejs').then(res => {
      resolve(res && res.data)
    }).catch(err => {
      reject(err)
    })
  })
}

module.exports = function(app) {
  app.use('/public', proxy({
    target: 'http://localhost:7000'
  }))
  app.get('*', (req, res, next) => {
    if(!serverBundle) {
      return res.send('watting for compile, refresh later');
    }
    getTemplate().then(template => {
      return serverRender(serverBundle, template, req, res);
    }).catch(next)
  })
}